Skip to content

🛡️ Sentinel: [CRITICAL] Fix command injection and secret leak in github-clone#33

Open
bobdivx wants to merge 1 commit into
devfrom
sentinel-github-clone-injection-10633150506117268059
Open

🛡️ Sentinel: [CRITICAL] Fix command injection and secret leak in github-clone#33
bobdivx wants to merge 1 commit into
devfrom
sentinel-github-clone-injection-10633150506117268059

Conversation

@bobdivx
Copy link
Copy Markdown
Owner

@bobdivx bobdivx commented May 14, 2026

🚨 Severity: CRITICAL
đź’ˇ Vulnerability:

  1. The /api/github-clone endpoint executed the git clone command using exec with string interpolation, exposing the application to command injection via the repoUrl and repoName parameters.
  2. Even without full command injection, the parameters could start with -, leading to flag injection.
  3. If the cloning command failed, the Node.js exec error object included the full command string, including the oauth2 token. This error message was passed back to the client directly, leaking the GitHub token.

🎯 Impact:

  • Arbitrary command execution on the host machine.
  • Leakage of the privileged GitHub access token to any user calling the endpoint.

đź”§ Fix:

  1. Refactored exec to execFile using argument arrays, entirely bypassing the shell and mitigating command injection.
  2. Added strict input validation to block hyphens (-) at the start of parameters to prevent flag injection.
  3. Added a regex replacement over the error message to explicitly redact the oauth2 token before returning the 500 error response to the client.
  4. Added an entry to .jules/sentinel.md outlining the learning that child_process error messages inherently leak arguments, necessitating redaction when secrets are passed.

âś… Verification:

  • Ran pnpm run check and pnpm test successfully.
  • Code review assessed the changes as Correct and properly securing the vulnerability.

PR created automatically by Jules for task 10633150506117268059 started by @bobdivx

…ub-clone

Co-authored-by: bobdivx <6737167+bobdivx@users.noreply.github.com>
@google-labs-jules
Copy link
Copy Markdown

đź‘‹ Jules, reporting for duty! I'm here to lend a hand with this pull request.

When you start a review, I'll add a đź‘€ emoji to each comment to let you know I've read it. I'll focus on feedback directed at me and will do my best to stay out of conversations between you and other bots or reviewers to keep the noise down.

I'll push a commit with your requested changes shortly after. Please note there might be a delay between these steps, but rest assured I'm on the job!

For more direct control, you can switch me to Reactive Mode. When this mode is on, I will only act on comments where you specifically mention me with @jules. You can find this option in the Pull Request section of your global Jules UI settings. You can always switch back!

New to Jules? Learn more at jules.google/docs.


For security, I will only act on instructions from the user who triggered this task.

@vercel
Copy link
Copy Markdown

vercel Bot commented May 14, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
forge Ready Ready Preview, Comment May 14, 2026 5:54pm

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request enhances the security of the GitHub cloning API by transitioning from exec to execFile to mitigate command injection risks and implementing token redaction in error responses. It also includes documentation on preventing secret leakage. Feedback highlights the need for more robust validation of repoName to prevent path traversal and recommends returning generic error messages to the client to avoid information exposure, even when sanitized.

Comment on lines +20 to +21
if (repoUrl.startsWith('-') || repoName.startsWith('-')) {
return new Response(JSON.stringify({ error: 'Les paramètres ne peuvent pas commencer par un tiret' }), { status: 400 });
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The current validation only checks for leading hyphens to prevent flag injection. However, repoName is used in a path.join operation and as a directory argument for git clone, making it susceptible to path traversal attacks (e.g., repoName being ../../etc). Additionally, since these values come from a JSON request, their types should be verified to ensure they are strings before calling .startsWith() to avoid potential runtime errors.

    const isSafeName = typeof repoName === 'string' && /^[a-zA-Z0-9._-]{1,128}$/.test(repoName) && repoName !== '..' && repoName !== '.';
    if (typeof repoUrl !== 'string' || repoUrl.startsWith('-') || !isSafeName) {
      return new Response(JSON.stringify({ error: 'Paramètres invalides ou nom de dépôt non sécurisé' }), { status: 400 });

return new Response(JSON.stringify({ error: error.message || 'Erreur lors du clonage' }), {
// 🛡️ Security: Sanitize error message to prevent leaking GitHub token to the client
// since Node.js exec/execFile errors include the command executed
const safeErrorMsg = (error.message || 'Erreur lors du clonage').replace(/oauth2:[^@]+@/g, 'oauth2:***@');
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

While redacting the token from the error message is a necessary step when using execFile, returning the raw error message to the client is still a security risk (Information Exposure). It can reveal internal paths, environment details, or software versions. It is recommended to log the full error on the server and return a generic error message to the user, as also suggested in your .jules/sentinel.md file.

    // Log the error server-side for debugging
    console.error('[github-clone] Error:', error);
    const safeErrorMsg = 'Erreur lors du clonage du dépôt. Veuillez vérifier l\'URL et le nom du dépôt.';

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant